package com.demo.practiceui.views.chart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * 热力图
 * 核心知识点：
 * 1. 二维数组数据可视化
 * 2. 颜色插值 - 根据数值生成渐变色
 * 3. 矩形网格绘制
 * 4. 数据归一化
 */
public class HeatMapView extends View {

    // 数据（模拟一周每小时的活跃度）
    private float[][] data = {
            {10, 5, 3, 2, 1, 2, 5, 20, 45, 60, 55, 50, 48, 52, 58, 62, 65, 70, 75, 60, 40, 30, 20, 15},
            {12, 6, 4, 3, 2, 3, 6, 22, 48, 63, 58, 53, 50, 55, 60, 65, 68, 73, 78, 63, 43, 32, 22, 17},
            {15, 8, 5, 4, 3, 4, 8, 25, 50, 65, 60, 55, 52, 57, 62, 67, 70, 75, 80, 65, 45, 35, 25, 20},
            {18, 10, 7, 5, 4, 5, 10, 28, 52, 67, 62, 57, 54, 59, 64, 69, 72, 77, 82, 67, 47, 37, 27, 22},
            {20, 12, 9, 7, 6, 7, 12, 30, 55, 70, 65, 60, 57, 62, 67, 72, 75, 80, 85, 70, 50, 40, 30, 25},
            {25, 15, 12, 10, 8, 10, 15, 35, 60, 75, 70, 65, 62, 67, 72, 77, 80, 85, 90, 75, 55, 45, 35, 30},
            {22, 13, 10, 8, 7, 8, 13, 32, 57, 72, 67, 62, 59, 64, 69, 74, 77, 82, 87, 72, 52, 42, 32, 27}
    };

    private String[] rowLabels = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
    private String[] colLabels = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
            "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"};

    // 画笔
    private Paint cellPaint;
    private Paint textPaint;

    // 尺寸
    private int width;
    private int height;
    private float cellWidth;
    private float cellHeight;
    private float paddingLeft = 100f;
    private float paddingTop = 80f;

    private float maxValue = 100f;  // 数据最大值
    private float minValue = 0f;    // 数据最小值

    public HeatMapView(Context context) {
        this(context, null);
    }

    public HeatMapView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HeatMapView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        // 单元格画笔
        cellPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        cellPaint.setStyle(Paint.Style.FILL);

        // 文字画笔
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.parseColor("#333333"));
        textPaint.setTextSize(24f);
        textPaint.setTextAlign(Paint.Align.CENTER);

        // 计算数据范围
        calculateRange();
    }

    /**
     * 计算数据的最大最小值
     */
    private void calculateRange() {
        maxValue = Float.MIN_VALUE;
        minValue = Float.MAX_VALUE;

        for (float[] row : data) {
            for (float value : row) {
                maxValue = Math.max(maxValue, value);
                minValue = Math.min(minValue, value);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthMode == MeasureSpec.AT_MOST) {
            width = 1200;
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            height = 600;
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;

        // 计算单元格尺寸
        int rows = data.length;
        int cols = data[0].length;
        cellWidth = (width - paddingLeft - 50) / cols;
        cellHeight = (height - paddingTop - 50) / rows;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 1. 绘制热力图单元格
        drawHeatMapCells(canvas);

        // 2. 绘制行标签
        drawRowLabels(canvas);

        // 3. 绘制列标签
        drawColLabels(canvas);

        // 4. 绘制图例
        drawLegend(canvas);
    }

    /**
     * 绘制热力图单元格
     */
    private void drawHeatMapCells(Canvas canvas) {
        int rows = data.length;
        int cols = data[0].length;

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                float value = data[i][j];

                // 计算单元格位置
                float left = paddingLeft + j * cellWidth;
                float top = paddingTop + i * cellHeight;
                float right = left + cellWidth;
                float bottom = top + cellHeight;

                // 根据数值计算颜色
                int color = getHeatColor(value);
                cellPaint.setColor(color);

                // 绘制单元格
                RectF rect = new RectF(left + 2, top + 2, right - 2, bottom - 2);
                canvas.drawRect(rect, cellPaint);
            }
        }
    }

    /**
     * 绘制行标签
     */
    private void drawRowLabels(Canvas canvas) {
        textPaint.setTextAlign(Paint.Align.RIGHT);
        for (int i = 0; i < rowLabels.length; i++) {
            float x = paddingLeft - 20;
            float y = paddingTop + i * cellHeight + cellHeight / 2 + 8;
            canvas.drawText(rowLabels[i], x, y, textPaint);
        }
    }

    /**
     * 绘制列标签
     */
    private void drawColLabels(Canvas canvas) {
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(20f);
        
        // 每隔几小时显示一个标签，避免拥挤
        for (int i = 0; i < colLabels.length; i += 2) {
            float x = paddingLeft + i * cellWidth + cellWidth / 2;
            float y = paddingTop - 20;
            canvas.drawText(colLabels[i] + "h", x, y, textPaint);
        }
        
        textPaint.setTextSize(24f);
    }

    /**
     * 绘制图例
     */
    private void drawLegend(Canvas canvas) {
        float legendX = paddingLeft;
        float legendY = height - 30;
        float legendWidth = 400;
        float legendHeight = 20;
        int steps = 10;

        // 绘制渐变色条
        for (int i = 0; i < steps; i++) {
            float value = minValue + (maxValue - minValue) * i / steps;
            int color = getHeatColor(value);
            cellPaint.setColor(color);

            float left = legendX + i * (legendWidth / steps);
            canvas.drawRect(left, legendY, left + legendWidth / steps, legendY + legendHeight, cellPaint);
        }

        // 绘制图例文字
        textPaint.setTextAlign(Paint.Align.LEFT);
        textPaint.setTextSize(20f);
        canvas.drawText(String.format("%.0f", minValue), legendX, legendY - 10, textPaint);
        
        textPaint.setTextAlign(Paint.Align.RIGHT);
        canvas.drawText(String.format("%.0f", maxValue), legendX + legendWidth, legendY - 10, textPaint);
        
        textPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText("活跃度", legendX + legendWidth / 2, legendY - 10, textPaint);
    }

    /**
     * 根据数值计算热力颜色
     * 从蓝色（低）到红色（高）渐变
     */
    private int getHeatColor(float value) {
        // 归一化值到0-1
        float normalized = (value - minValue) / (maxValue - minValue);

        // 颜色渐变：蓝色 -> 青色 -> 绿色 -> 黄色 -> 红色
        int r, g, b;
        if (normalized < 0.25f) {
            // 蓝色到青色
            float t = normalized / 0.25f;
            r = 0;
            g = (int) (255 * t);
            b = 255;
        } else if (normalized < 0.5f) {
            // 青色到绿色
            float t = (normalized - 0.25f) / 0.25f;
            r = 0;
            g = 255;
            b = (int) (255 * (1 - t));
        } else if (normalized < 0.75f) {
            // 绿色到黄色
            float t = (normalized - 0.5f) / 0.25f;
            r = (int) (255 * t);
            g = 255;
            b = 0;
        } else {
            // 黄色到红色
            float t = (normalized - 0.75f) / 0.25f;
            r = 255;
            g = (int) (255 * (1 - t));
            b = 0;
        }

        return Color.rgb(r, g, b);
    }

    /**
     * 设置数据
     */
    public void setData(float[][] data, String[] rowLabels, String[] colLabels) {
        this.data = data;
        this.rowLabels = rowLabels;
        this.colLabels = colLabels;
        calculateRange();
        invalidate();
    }
}

